package com.xy6.dpdemo.book.chapter24.chain;

import com.xy6.dpdemo.book.chapter24.chain.service.Handler;
import com.xy6.dpdemo.book.chapter24.chain.service.HandlerDM;
import com.xy6.dpdemo.book.chapter24.chain.service.HandlerGL;
import com.xy6.dpdemo.book.chapter24.chain.service.HandlerPM;

/**
 * 设计一个程序，模拟员工提出加薪申请，项目经理、部门经理等一级一级审批的过程
 * <p>员工提出加薪、请假等申请，提交流程，项目经理处理，有权则处理，无权则流程继续。
 * 部门经理处理，有权则处理，无权则流程继续。
 * 
 * <pre>
 * 创建申请单类，创建审批类，定义审批方法。审批时，判断审批人身份、申请单类型，如果两者匹配，则通过，
 * 如果不匹配，则无权审批。缺点：所有对象耦合在一个方法中，违反单一职责原则。如果添加或删除一个层级，
 * 则需要修改方法，违反开放-关闭原则。
 * 
 * 改：创建处理接口，定义设置处理人方法、处理方法，创建具体处理人类，如组长、项目经理。
 * 客户端调用时，先定义处理流程上各处理人，再提交申请。好处：不同处理人在不同类中，审批规则定义在各自类中，
 * 达到解耦。添加或删除一个层级，不需要修改接口代码，只需修改客户端代码。
 * 
 * 职责链模式。使多个对象都有机会处理请求，从而避免请求的发送者和接收者之间的耦合关系。将对象练成一条链，
 * 沿着这条链传递该请求，直到有一个对象处理它为止。
 * 关键点：当客户提交一个请求时，请求沿链传递，直至有一个ConcreteHandler对象负责处理它。
 * 隐患：一个请求极有可能到了链的末端都得不到处理，或者因为没有正确配置而得不到处理。设计时应考虑。
 * </pre>
 * 
 * @author zhang
 * @since 2017-07-10
 */
public class SalaryMain {

	public static void main(String[] args) {
		test2();
	}
	
	@SuppressWarnings("unused")
	private static void test1(){
		Request req = new Request();
		req.setType(RequestTypeEnum.ILL.getType());
		req.setNum(3);
		
		Approve gl = new Approve(ApproverEnum.GROUP_LEADER.getType());
		Approve pm = new Approve(ApproverEnum.PROJECT_MANAGER.getType());
		Approve dm = new Approve(ApproverEnum.DEPT_MANAGER.getType());
		Approve boss = new Approve(ApproverEnum.BOSS.getType());
		gl.approve(req);
		
		Request req2 = new Request();
		req2.setType(RequestTypeEnum.SALARY.getType());
		req2.setNum(5000);
		
		gl.approve(req2);
		pm.approve(req2);
		dm.approve(req2);
		boss.approve(req2);
	}
	
	private static void test2(){
		// 定义职责链
		Handler h1 = new HandlerGL();
		Handler h2 = new HandlerPM();
		Handler h3 = new HandlerDM();
		h1.setSuccessor(h2);
		h2.setSuccessor(h3);
		
		// 申请1
		Request req = new Request();
		req.setType(RequestTypeEnum.ILL.getType());
		req.setNum(3);
		
		// 申请2
		Request req2 = new Request();
		req2.setType(RequestTypeEnum.SALARY.getType());
		req2.setNum(5000);
		
		// 提交申请
		h1.handle(req);
		h1.handle(req2);
	}

}
